home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / libg_261.zip / libg_261 / libg++ / old-stream / Filebuf.cc < prev    next >
C/C++ Source or Header  |  1992-01-17  |  7KB  |  327 lines

  1. /* 
  2. Copyright (C) 1990 Free Software Foundation
  3.     written by Doug Lea (dl@rocky.oswego.edu)
  4.  
  5. This file is part of the GNU C++ Library.  This library is free
  6. software; you can redistribute it and/or modify it under the terms of
  7. the GNU Library General Public License as published by the Free
  8. Software Foundation; either version 2 of the License, or (at your
  9. option) any later version.  This library is distributed in the hope
  10. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  11. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. PURPOSE.  See the GNU Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  16. */
  17.  
  18. #ifdef __GNUG__
  19. #pragma implementation
  20. #endif
  21.  
  22. #include <Filebuf.h>
  23.  
  24. #include <std.h>
  25. #include <sys/file.h>           // needed to determine values of O_RDONLY...
  26.  
  27. #ifndef _bufsiz
  28. #ifdef masscomp
  29. #ifdef _UCB
  30. #define _bufsiz(p) 4096
  31. #endif
  32. #else
  33. #define _bufsiz(p) ((p)->_bufsiz)
  34. #endif
  35. #endif
  36.  
  37. #ifdef VMS
  38. #include <assert.h>
  39. #define FPOINT (*(Fp->fp))
  40. #undef _bufsiz
  41. #define _bufsiz(p) BUFSIZ    // we do not have this available
  42. #else
  43. #define FPOINT Fp->fp 
  44. #endif
  45.  
  46. void Filebuf::init_streambuf_ptrs()
  47. {
  48.   if (Fp->fp == 0 || FPOINT->_cnt == 0)
  49.   {
  50.     base = gptr = pptr = eptr = 0; // let first over/under flow deal with it
  51.   }
  52.   else
  53.   {
  54. #ifdef VMS
  55.     base = new char[BUFSIZ];
  56.     alloc = 1;
  57. #else
  58.     base = FPOINT->_base;
  59. #endif
  60.     eptr = base - 1 + _bufsiz(Fp->fp);
  61.     pptr = gptr = base;
  62.   }
  63. }
  64.  
  65.  
  66. int Filebuf::is_open()
  67. {
  68.   return (Fp != 0 && Fp->is_open());
  69. }
  70.  
  71.  
  72. streambuf* Filebuf::open(const char* name, io_mode m, access_mode a)
  73. {
  74.   if (Fp == 0)
  75.     Fp = new File(name, m, a);
  76.   else
  77.     Fp->open(name, m, a);
  78. #ifndef VMS
  79.   if (base != 0) Fp->setbuf(eptr-base+1, base);
  80. #endif
  81.   init_streambuf_ptrs();
  82.   return this;
  83. }
  84.  
  85. streambuf* Filebuf::open(const char* name, const char* m)
  86. {
  87.   if (Fp == 0)
  88.     Fp = new File(name, m);
  89.   else
  90.     Fp->open(name, m);
  91. #ifndef VMS
  92.   if (base != 0) Fp->setbuf(eptr-base+1, base);
  93. #endif
  94.   init_streambuf_ptrs();
  95.   return this;
  96. }
  97.  
  98. streambuf*  Filebuf::open(const char* name, open_mode m)
  99. {
  100.   switch(m)
  101.   {
  102.   case input: return open(name, "r"); 
  103.   case output: return open(name, "w");
  104.   case append: return open(name, "a");
  105.   }
  106. }
  107.  
  108. streambuf* Filebuf::open(int filedesc, io_mode m)
  109. {
  110.   if (Fp == 0)
  111.     Fp = new File(filedesc, m);
  112.   else
  113.     Fp->open(filedesc, m);
  114. #ifndef VMS
  115.   if (base != 0) Fp->setbuf(eptr-base+1, base);
  116. #endif
  117.   init_streambuf_ptrs();
  118.   return this;
  119. }
  120.  
  121. streambuf* Filebuf::open(FILE* fileptr)
  122. {
  123.   if (Fp == 0)
  124.     Fp = new File(fileptr);
  125.   else
  126.     Fp->open(fileptr);
  127. #ifndef VMS
  128.   if (base != 0) Fp->setbuf(eptr-base+1, base);
  129. #endif
  130.   init_streambuf_ptrs();
  131.   return this;
  132. }
  133.  
  134. Filebuf::Filebuf() : streambuf(), Fp(0) {}
  135.  
  136. Filebuf::Filebuf(const char* filename, io_mode m, access_mode a)
  137.      : streambuf()
  138. {
  139.   Fp = new File(filename, m, a);
  140.   init_streambuf_ptrs();
  141. }
  142.  
  143. Filebuf::Filebuf(const char* filename, const char* m)
  144.      : streambuf()
  145. {
  146.   Fp = new File(filename, m);
  147.   init_streambuf_ptrs();
  148. }
  149.  
  150. Filebuf::Filebuf(int filedesc, io_mode m)
  151.      : streambuf()
  152. {
  153.   Fp = new File(filedesc, m);
  154.   init_streambuf_ptrs();
  155. }
  156.  
  157. Filebuf::Filebuf(FILE* fileptr)
  158.      : streambuf()
  159. {
  160.   Fp = new File(fileptr);
  161.   init_streambuf_ptrs();
  162. }
  163.  
  164. int Filebuf::close()
  165. {
  166.   int was = Fp->is_open();
  167.   if (was) { overflow(); Fp->close(); }
  168. #ifdef VMS
  169.   if (was) {
  170.     if(alloc && (base != 0)) {delete base; base=0; alloc = 0;};
  171.     gptr=0;};
  172. #endif
  173.   return was;
  174. }
  175.  
  176.  
  177. Filebuf::~Filebuf()
  178. {
  179.   if (Fp != 0)
  180.   {
  181.     close();
  182.     delete Fp;
  183.   }
  184. }
  185.  
  186. #ifdef VMS
  187. /*
  188.     VMS implementation notes:
  189.  The underflow routine works fine as long as there is no mixing of input and
  190.  output for the same stream.  If this were to happen, then great confusion
  191.  would occur, since we maintain a seperate buffer for the case of output.
  192.  the stream classes do not allow this as they are currently written, so for
  193.  now we are OK.  VMS does not handle buffered output in quite the same way
  194.  that UNIX does, so a seperate buffer is allocated, and used by the program.
  195.  when it comes time to flush it we call write(...) to empty it.  The flush
  196.  function under VMS does not flush the buffer unless it is full, and whatsmore
  197.  the _iobuf is not 14 bytes long as one might suspect from the structure def,
  198.  but at *least* 66 bytes long.  Some of these hidden structure elements need
  199.  to be set for the output to work properly, and it seemed to be poor
  200.  programming practice to fool with them
  201. */
  202. #endif
  203. /*
  204.   The underflow and overflow methods sync the streambuf with the _iobuf
  205.   ptrs on the way in and out of the read. I believe that this is
  206.   done in a portable way.
  207. */
  208. int Filebuf::underflow()
  209. {
  210.   int ch;
  211.   if (Fp == 0) return EOF;
  212.   if (gptr == 0) // stdio _iobuf ptrs not initialized until after 1st read
  213.   {
  214. #ifdef VMS
  215.     assert(alloc==0);
  216. #endif
  217.     ch = Fp->fill();
  218.     base = FPOINT->_base;
  219.     eptr = base - 1 + _bufsiz(Fp->fp);
  220.   }
  221.   else
  222.   {
  223.     FPOINT->_ptr = gptr;
  224.     FPOINT->_cnt = eptr - gptr + 1;
  225.     ch = Fp->fill();
  226.   }
  227.   gptr = base;
  228.   *gptr = ch;
  229.   if (ch == EOF)
  230.     pptr = base;
  231.   else
  232.     pptr = base + FPOINT->_cnt + 1;
  233.   if (Fp->good())
  234.     return ch;
  235.   else
  236.   {
  237.     Fp->clear();
  238.     return EOF;
  239.   }
  240. }
  241.  
  242. int Filebuf::overflow(int ch)
  243. {
  244.   if (Fp == 0) return EOF;
  245.   if (FPOINT->_flag & _IONBF)  // handle unbuffered IO specially
  246.   {
  247.     if (pptr == 0) // 1st write
  248.     {
  249.       if (ch == EOF)
  250.         return 0;
  251.       else
  252.       {
  253.         Fp->flush(ch);
  254.       }
  255.     }
  256.     else
  257.     {
  258.       if (ch == EOF)
  259.         Fp->flush();        // Probably not necessary
  260.       else
  261.         Fp->flush(ch);
  262.     }
  263.   }
  264.   else
  265.   {
  266.     if (pptr == 0) // 1st write
  267.     {
  268.       if (ch == EOF)
  269.         return 0;
  270.       else
  271.       {
  272.         Fp->flush(ch);
  273. #ifdef VMS
  274.         base = new char[BUFSIZ];
  275.         alloc = 1;
  276. #else
  277.         base = FPOINT->_base;
  278. #endif
  279.         eptr = base - 1 + _bufsiz(Fp->fp);
  280.         gptr = base;
  281.       }
  282.     }
  283.     else
  284.     {
  285.       if (ch != EOF) *pptr++ = ch;
  286. #ifdef VMS
  287.       if(gptr==base) write(FPOINT->_file,base,pptr-base);
  288. #else
  289.       FPOINT->_ptr = pptr;
  290.       FPOINT->_cnt = eptr - pptr + 1;
  291. #endif
  292.       Fp->flush();
  293.     }
  294. #ifdef VMS
  295.     pptr = base;
  296. #else
  297.     pptr = FPOINT->_ptr;
  298. #endif
  299.   }
  300.   if (Fp->fail() || Fp->bad())
  301.   {
  302.     Fp->clear(); // this allows recovery from ostream level
  303.     return EOF;
  304.   }
  305.   else
  306.     return 0;
  307. }
  308.  
  309. const char* Filebuf::name()
  310. {
  311.   return Fp->name();
  312. }
  313.  
  314. streambuf* Filebuf::setbuf(char* buf, int buflen, int preload)
  315. {
  316.   if (preload != 0) return 0; // cannot preload, sorry
  317.   if (Fp != 0) Fp = new File;
  318.   Fp->setbuf(buflen, buf);
  319.   init_streambuf_ptrs();
  320.   return (Fp->good())? this : 0;
  321. }
  322.  
  323. void Filebuf::error()
  324. {
  325.   Fp->error();
  326. }
  327.